package com.sunny.springboot2.hash;

import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import org.springframework.stereotype.Service;

import java.util.SortedMap;
import java.util.TreeMap;

/**
 * hash
 * @author sunny
 */
@Service
public class PartitionByMurmurHash {

    private static final int DEFAULT_VIRTUAL_BUCKET_TIMES = 160;
    // 每张表权重是1，即均衡分布
    private static final int DEFAULT_WEIGHT = 1;
    private HashFunction hash = null;
    private SortedMap<Integer, Integer> bucketMap;

    private int count = 5;

    /**
     * tailMap获取tree中大于或等于fromKey的视图
     * @param partitionKey
     * @return 返回hash环中大于或等于fromKey的第一个key
     */
    public Integer calculate(String partitionKey) {
        int asInt = hash.hashUnencodedChars(partitionKey).asInt();
        SortedMap<Integer, Integer> tail = bucketMap.tailMap(asInt);
        return tail.isEmpty() ? (Integer) bucketMap.get(bucketMap.firstKey())
                : (Integer) tail.get(tail.firstKey());
    }


    public PartitionByMurmurHash() {
        initBucket();
    }

    /**
     * 初始化桶，构造hash环（红黑树）
     */
    private void initBucket() {
        if(hash == null) {
            hash = Hashing.murmur3_32(0);
        }

        if(bucketMap == null) {
            bucketMap = new TreeMap<>();
            for (int i = 1; i <= count; ++i) {
                StringBuilder hashName = (new StringBuilder("SHARD-")).append(i);
                for (int j = 0; j < DEFAULT_VIRTUAL_BUCKET_TIMES * DEFAULT_WEIGHT ; ++ j) {
                    int asInt = hash.hashUnencodedChars(hashName.append("-NODE-").append(j)).asInt();
                    bucketMap.put(asInt, i);
                }
            }
        }
    }

    public static void main(String[] args) {
    PartitionByMurmurHash partitionByMurmurHash = new PartitionByMurmurHash();
        Integer index = partitionByMurmurHash.calculate("az5625418");
        System.out.println(index);
    }

}
